/* Copyright (c) 2004-2024 Peigen.info. All rights reserved. */

package info.peigen.hotpot.component.open.api.core.web;


import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import info.peigen.hotpot.component.open.api.core.service.OpenApiCallbackService;
import info.peigen.hotpot.component.open.api.core.service.OpenApiService;
import info.peigen.hotpot.component.open.api.core.service.OpenSimpleApiService;
import info.peigen.hotpot.component.open.api.core.web.form.ApiForm;
import info.peigen.hotpot.component.open.api.core.web.result.ApiResult;
import info.peigen.hotpot.component.open.api.facade.order.OpenApiCallbackOrder;
import info.peigen.hotpot.component.open.api.facade.order.OpenApiOrder;
import info.peigen.hotpot.component.open.api.facade.result.OpenListResult;
import info.peigen.hotpot.component.open.api.facade.result.OpenPageResult;
import info.peigen.hotpot.component.open.api.facade.result.OpenSingleResult;
import info.peigen.hotpot.component.upload.service.UploadService;
import info.peigen.hotpot.component.upload.service.order.UploadBatchOrder;
import info.peigen.hotpot.component.upload.service.order.UploadOrder;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.*;
import org.noear.solon.core.handle.UploadedFile;
import org.noear.solon.validation.annotation.Validated;
import org.noear.solon.web.cors.annotation.CrossOrigin;

import static org.noear.solon.core.handle.MethodType.POST;

/**
 * <b>(OpenApiController)</b>
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2021/8/8
 */
@SuppressWarnings("rawtypes")
@CrossOrigin
@Controller
@Slf4j
public class OpenApiController {
    static final String RESULT_TYPE_SINGLE = "single";
    static final String RESULT_TYPE_LIST   = "list";
    static final String RESULT_TYPE_PAGE   = "page";
    @Inject
    OpenApiService         openApiService;
    @Inject
    OpenApiCallbackService openApiCallbackService;
    @Inject
    OpenSimpleApiService   openSimpleApiService;
    @Inject
    UploadService          uploadService;

    @Mapping(value = "/api", method = POST, consumes = "application/json; charset=UTF-8")
    public ApiResult api(@Validated @Body ApiForm form) {
        OpenApiOrder order = BeanUtil.copyProperties(form, OpenApiOrder.class);
        ApiResult    apiResult;
        switch (form.getResultType()) {
            case RESULT_TYPE_PAGE:
                OpenPageResult pageResult = openApiService.pageService(order);
                apiResult = BeanUtil.copyProperties(pageResult, ApiResult.class, "info");
                apiResult.setInfo(pageResult);
                apiResult.setRequestNo(order.getRequestNo());
                apiResult.setToken(pageResult.getToken());
                break;
            case RESULT_TYPE_LIST:
                OpenListResult listResult = openApiService.listService(order);
                apiResult = BeanUtil.copyProperties(listResult, ApiResult.class);
                apiResult.setToken(listResult.getToken());
                break;
            case RESULT_TYPE_SINGLE:
            default:
                OpenSingleResult singleResult = openApiService.service(order);
                apiResult = BeanUtil.copyProperties(singleResult, ApiResult.class);
                apiResult.setToken(singleResult.getToken());
                break;
        }
        apiResult.setRequestNo(order.getRequestNo());
        return apiResult;
    }

    /**
     * 针对各业务的回调接口
     *
     * @param data         数据
     * @param methodType   格式
     * @param callType     调用方式
     * @param businessType 业务类型
     *
     * @return ApiResult
     */
    @Mapping(value = "/api/callback/{methodType}/{callType}/{businessType}")
    public ApiResult callbackApi(@Body String data,
                                 @Path("methodType") String methodType,
                                 @Path("callType") String callType,
                                 @Path("businessType") String businessType) {
        log.info("接收到回调信息：methodType=" + methodType + ",callType=" + callType + ",businessType=" + businessType + ",data=" + data);
        OpenApiCallbackOrder order = OpenApiCallbackOrder.builder().data(data).callType(callType)
                .methodType(methodType).businessType(businessType).build();
        OpenSingleResult openSingleResult = openApiCallbackService.service(order);
        return BeanUtil.copyProperties(openSingleResult, ApiResult.class);
    }

    /**
     * 不对入参进行加密验证和签名
     *
     * @param form ApiForm
     *
     * @return ApiResult
     */
    @Mapping(value = "/api/simple", method = POST)
    public ApiResult simpleApi(ApiForm form) {
        OpenApiOrder order = BeanUtil.copyProperties(form, OpenApiOrder.class);

        ApiResult apiResult;
        switch (form.getResultType()) {
            case RESULT_TYPE_PAGE:
                OpenPageResult pageResult = openSimpleApiService.pageService(order);
                apiResult = BeanUtil.copyProperties(pageResult, ApiResult.class, "info");
                apiResult.setInfo(pageResult);
                apiResult.setRequestNo(order.getRequestNo());
                apiResult.setToken(pageResult.getToken());
                break;
            case RESULT_TYPE_LIST:
                OpenListResult listResult = openSimpleApiService.listService(order);
                apiResult = BeanUtil.copyProperties(listResult, ApiResult.class);
                apiResult.setToken(listResult.getToken());
                break;
            case RESULT_TYPE_SINGLE:
            default:
                OpenSingleResult singleResult = openSimpleApiService.service(order);
                apiResult = BeanUtil.copyProperties(singleResult, ApiResult.class);
                apiResult.setToken(singleResult.getToken());
                break;
        }
        apiResult.setRequestNo(order.getRequestNo());
        return apiResult;
    }

    @Mapping("/api/upload")
    public String upload(@Param("file") UploadedFile file) {
        UploadOrder order = UploadOrder.builder().uploadedFile(file).build();
        return JSON.toJSONString(uploadService.upload(order));
    }

    @Mapping("/api/uploads")
    public String uploads(@Param("files") UploadedFile[] files) {
        UploadBatchOrder order = UploadBatchOrder.builder().uploadedFileList(Lists.newArrayList(files)).build();
        return JSON.toJSONString(uploadService.uploadBatch(order));
    }
}